package com.young.freedom.spring.aop.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.young.freedom.aop.AuditCode;
import com.young.freedom.aop.Auditable;

@Component
@Aspect
public class NotVeryUsefulAspect {
	
	static final Logger logger = LoggerFactory.getLogger(NotVeryUsefulAspect.class);
	
	@Pointcut("execution(public * *(..))")
	public void anyPublicOperation() {}
	
	@Pointcut("within(com.young.project.freedom.aop.*)")
	public void inTrading() {}
	
	@Pointcut("anyPublicOperation() && inTrading()")
	public void tradingOperation() {}
	
	@Pointcut("anyPublicOperation() && @annotation(auditable)")
	public void annotationOperation(Auditable auditable){}
	
	
	
	@Before("anyPublicOperation() && args(account,..)")
	public void beforeAdvice(String account){
		logger.info("This is the BeforeAdvice()"+account);
	}
	
//	@Before("annotationOperation(auditable)")
//	public void beforeAnnotationAdvice(Auditable auditable){
//		AuditCode code = auditable.value();
//		logger.info(code.toString());
//	}
	
	@Before(
			value = "annotationOperation(auditable) && target(bean)"
//			argNames="bean,auditable"
			)
	public void beforeArgsAdivce(JoinPoint.StaticPart staticPart,Object bean,Auditable auditable){
		AuditCode code = auditable.value();
		logger.info(code.toString());
		logger.info(bean.toString());
		logger.info(staticPart.getKind());
		logger.info(staticPart.toLongString());
	}
	
//	@AfterReturning(
//			pointcut="execution(String com.young.project.freedom.aop.*.*(..) )",
//			returning="retVal"
//			)
//	public void afterReturningAdvice(Object retVal){
//		logger.info("This is the AfterAdvice()");
//		logger.info("The return value is:"+retVal);
//	}
	
	@AfterThrowing(
			pointcut="anyPublicOperation()",
			throwing="ex"
			)
	public void afterThrowingAdvice(RuntimeException ex){
		logger.info("This is the afterThrowingAdvice()");
		logger.info("Message is:"+ex);
	}
	
//	@Around("anyPublicOperation()")
//	public Object aroundAdvice(ProceedingJoinPoint point) throws Throwable{
//		logger.info("Begin around");
//		logger.info("getArgs()--"+point.getArgs());
//		for(Object obj : point.getArgs()){
//			logger.info("Arg is --"+obj);
//		}
//		logger.info("getTarget()--"+point.getTarget());
//		logger.info("getSignature()--"+point.getSignature());
//		logger.info("toString()--"+point.toString());
//		Object obj = point.proceed();
//		logger.info("End around");
//		return obj;
//	}
	
	@AfterReturning("anyPublicOperation()")
	public void commonAfterReturningAdvice(){
		logger.info("-------------------------------------------------------------------------------------------");
	}

}
